package com.wego.common.utils;

import java.security.MessageDigest;
import java.util.Random;

public class Md5Util {
    /**
     * 将字节数组 转换成 十六进制字符串
     *
     * @param arr 要转换的字节数组
     * @return String 返回十六进制字符串
     */
    private static String hex(byte[] arr) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < arr.length; ++i) {
            sb.append(Integer.toHexString((arr[i] & 0xFF) | 0x100).substring(1, 3));
        }
        return sb.toString();
    }

    /**
     * 获取十六进制字符串形式的MD5摘要 MD5加密,并把结果由字节数组转换成十六进制字符串
     *
     * @param str 要加密的内容
     * @return String 返回加密后的十六进制字符串
     */
    private static String md5Hex(String str) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] digest = md.digest(str.getBytes());
            return hex(digest);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 生成含有随机盐的密码
     *
     * @param plainText 要加密的密码
     * @return String 含有随机盐的密码
     */
    public static String encode(String plainText) {
        // 生成一个16位的随机数
        Random random = new Random();
        StringBuilder sb = new StringBuilder(16);
        sb.append(random.nextInt(99999999)).append(random.nextInt(99999999));
        int len = sb.length();
        if (len < 16) {
            for (int i = 0; i < 16 - len; i++) {
                sb.append("0");
            }
        }
        // 生成最终的加密盐
        String salt = sb.toString();

        plainText = md5Hex(plainText + salt);
        char[] cs = new char[48];
        for (int i = 0; i < 48; i += 3) {
            cs[i] = plainText.charAt(i / 3 * 2);
            char c = salt.charAt(i / 3);
            cs[i + 1] = c;
            cs[i + 2] = plainText.charAt(i / 3 * 2 + 1);
        }
        return String.valueOf(cs);
    }

    /**
     * 校验密码是否正确 验证加盐后是否和原密码一致
     *
     * @param plainText 原密码
     * @param plainText 加密之后的密码
     * @return true表示和原密码一致 false表示和原密码不一致
     */
    public static boolean verify(String plainText, String cypherText) {
        char[] cs1 = new char[32];
        char[] cs2 = new char[16];
        for (int i = 0; i < 48; i += 3) {
            cs1[i / 3 * 2] = cypherText.charAt(i);
            cs1[i / 3 * 2 + 1] = cypherText.charAt(i + 2);
            cs2[i / 3] = cypherText.charAt(i + 1);
        }
        String Salt = new String(cs2);
        return md5Hex(plainText + Salt).equals(String.valueOf(cs1));
    }

    public static void main(String[] args) {
        // 原文
        String plainText = "as我爱中_fd~ba";

        // 获取加盐后的MD5值
        String cipherText = Md5Util.encode(plainText);
        System.out.println("加盐后MD5：" + cipherText);
        System.out.println(cipherText.length());
        System.out.println("是否是同一字符串:" + Md5Util.verify(plainText, cipherText));
    }
}
